package org.hackystat.ui.projectviewer.gwt.client.panels;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.hackystat.ui.projectviewer.gwt.client.CSSStyles;
import org.hackystat.ui.projectviewer.gwt.client.ProjectViewer;
import org.hackystat.ui.projectviewer.gwt.client.common.MainPanelWidget;
import org.hackystat.ui.projectviewer.gwt.client.common.ProjectViewerException;
import org.hackystat.ui.projectviewer.gwt.client.common.types.ProjectData;
import org.hackystat.ui.projectviewer.gwt.client.widgets.PanelTitleWidget;

import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Allows project record editing.
 *
 * @author Pavel Senin.
 *
 */
public class EditProjectPanel extends MainPanelWidget {

  /**
   * Creates an instance and reports a handler.
   *
   * @param parent The handler top the "parent" window.
   * @return the widget handler.
   */
  public static MPHandler init(final ProjectViewer parent) {
    return new MPHandler("editProject") {
      public MainPanelWidget createInstance() {
        return new EditProjectPanel(parent);
      }
    };
  }

  // the main panel to hold all elements
  VerticalPanel outer = new VerticalPanel();

  // title
  private final PanelTitleWidget projectTitle = new PanelTitleWidget();

  // title edit panel in case we are making new project
  final Label titleLabel = new Label("Project name:");
  final TextBox titleBox = new TextBox();

  // the main grid to hold all elements
  FlexTable ft = new FlexTable();

  // labels and buttons

  // project owner
  final Label ownerLabel = new Label("Project owner:");
  final TextBox ownerBox = new TextBox();

  // project members
  final Label membersLabel = new Label("Project members:");
  final ListBox membersList = new ListBox();
  final VerticalPanel membersCell = new VerticalPanel();
  final HorizontalPanel membersMenu = new HorizontalPanel();
  final Button remMemberButton = new Button("remove");

  // project description
  final Label descLabel = new Label("Project description:");
  final TextBox descBox = new TextBox();

  // project timing - start and end
  final Label startTime = new Label("Project start time:");
  final TextBox startBox = new TextBox();
  final Label endTime = new Label("Project end time:");
  final TextBox endBox = new TextBox();

  // project URI's
  final Label uriLabel = new Label("Project URI patterns:");
  final ListBox uriList = new ListBox();
  final VerticalPanel uriCell = new VerticalPanel();
  final HorizontalPanel uriMenu = new HorizontalPanel();
  final Button newUriButton = new Button("add");
  final Button remUriButton = new Button("remove");

  // project properties
  final Label propertiesLabel = new Label("Project properties:");
  final ListBox propertiesList = new ListBox();
  final VerticalPanel propCell = new VerticalPanel();
  final HorizontalPanel propertiesMenu = new HorizontalPanel();
  final Button newPropButton = new Button("add");
  final Button remPropButton = new Button("remove");

  // project invitations
  final Label invitationsLabel = new Label("Project invitations:");
  final ListBox invitationsList = new ListBox();
  final VerticalPanel invitationsOuter = new VerticalPanel();
  final HorizontalPanel invitationsMenu = new HorizontalPanel();
  final Button newInviteeButton = new Button("new");
  final Button remInvitationButton = new Button("remove");

  // dialog buttons
  final Button okButton = new Button("Submit changes");
  final Button cancelButton = new Button("Cancel");

  final ProjectViewer parent;

  // private ProjectData pd;

  private boolean mode;

  /**
   * Instantiates the Project Edit panel.
   *
   * @param parent The parent panel link to get RPC provider for RPC calls.
   */
  public EditProjectPanel(final ProjectViewer parent) {

    this.parent = parent;
    outer.setStyleName("editProjectPanel");

    // add title to the panel
    projectTitle.setTitle("Edit project panel...");
    outer.add(projectTitle);

    outer.setWidth("100%");
    // this.pd = new ProjectData();

    // set up lists uniformly
    membersList.setVisibleItemCount(4);
    membersList.setTabIndex(-1);
    propertiesList.setVisibleItemCount(4);
    propertiesList.setTabIndex(-1);
    uriList.setVisibleItemCount(4);
    uriList.setTabIndex(-1);
    invitationsList.setVisibleItemCount(4);
    invitationsList.setTabIndex(-1);

    // init table holder and all fields
    titleLabel.setHorizontalAlignment(Label.ALIGN_LEFT);
    titleLabel.setWidth("10em");
    titleBox.setStyleName("box");
    titleBox.setWidth("20em");

    ft.setCellSpacing(5);

    ownerLabel.setWidth("10em");
    ownerBox.setStyleName("box");
    ownerBox.setWidth("20em");
    ownerBox.setEnabled(false);

    membersList.setWidth("20em");

    descBox.setStyleName("box");
    descBox.setWidth("20em");

    startBox.setStyleName("box");
    startBox.setWidth("20em");

    endBox.setStyleName("box");
    endBox.setWidth("20em");

    uriList.setWidth("20em");

    propertiesList.setWidth("20em");

    invitationsList.setWidth("20em");

    // populate labels and fields

    ft.setWidget(0, 0, ownerLabel);
    ft.setWidget(0, 1, ownerBox);

    // now working on the project members addition
    membersCell.setHeight("4em");
    membersCell.setVerticalAlignment(VerticalPanel.ALIGN_TOP);
    membersCell.add(membersLabel);
    remMemberButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        RemoveMemberDialog rmd = new RemoveMemberDialog(membersList);
        rmd.show();
        rmd.center();
      }
    });
    membersMenu.add(remMemberButton);
    membersMenu.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
    membersCell.add(membersMenu);
    ft.setWidget(1, 0, membersCell);
    membersList.setStyleName("box");
    ft.setWidget(1, 1, membersList);

    // PROJECT DESCRIPTION AND start end times
    ft.setWidget(2, 0, descLabel);
    ft.setWidget(2, 1, descBox);
    ft.setWidget(3, 0, startTime);
    ft.setWidget(3, 1, startBox);
    ft.setWidget(4, 0, endTime);
    ft.setWidget(4, 1, endBox);

    // now working on the uri addition
    uriCell.setHeight("100%");
    uriCell.setVerticalAlignment(VerticalPanel.ALIGN_TOP);
    uriCell.add(uriLabel);
    newUriButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        NewUriDialog nud = new NewUriDialog(uriList);
        nud.show();
        nud.center();
      }
    });
    remUriButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        RemoveUriDialog rud = new RemoveUriDialog(uriList);
        rud.show();
        rud.center();
      }
    });
    uriMenu.add(newUriButton);
    uriMenu.add(remUriButton);
    uriCell.add(uriMenu);
    ft.setWidget(5, 0, uriCell);
    uriList.setStyleName("box");
    ft.setWidget(5, 1, uriList);

    // properties
    propCell.setHeight("100%");
    propCell.setVerticalAlignment(VerticalPanel.ALIGN_TOP);
    propCell.add(propertiesLabel);
    newPropButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        NewPropDialog npd = new NewPropDialog(propertiesList);
        npd.show();
        npd.center();
      }
    });
    remPropButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        RemovePropDialog rpd = new RemovePropDialog(propertiesList);
        rpd.show();
        rpd.center();
      }
    });
    propertiesMenu.add(newPropButton);
    propertiesMenu.add(remPropButton);
    propCell.add(propertiesMenu);
    ft.setWidget(6, 0, propCell);
    propertiesList.setStyleName("box");
    ft.setWidget(6, 1, propertiesList);

    // now working on the project invitations addition
    invitationsOuter.setHeight("4em");
    invitationsOuter.setVerticalAlignment(VerticalPanel.ALIGN_TOP);
    invitationsOuter.add(invitationsLabel);
    newInviteeButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        NewInviteeDialog nid = new NewInviteeDialog(invitationsList);
        nid.show();
        nid.center();
      }
    });
    remInvitationButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        RemoveInvitationDialog rid = new RemoveInvitationDialog(invitationsList);
        rid.show();
        rid.center();
      }
    });
    invitationsMenu.add(newInviteeButton);
    invitationsMenu.add(remInvitationButton);
    invitationsOuter.add(invitationsMenu);
    ft.setWidget(7, 0, invitationsOuter);
    invitationsList.setStyleName("box");
    ft.setWidget(7, 1, invitationsList);

    // add whole FlexTable to the main panel
    outer.add(ft);

    // now take care about dialog buttons
    HorizontalPanel buttonsPanel = new HorizontalPanel();
    buttonsPanel.add(okButton);
    okButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        ProjectData success = updateProject(titleBox.getText(), ownerBox.getText(), membersList,
            descBox.getText(), startBox.getText(), endBox.getText(), uriList, propertiesList,
            invitationsList);
        if (null == success) {
          Window.alert("Unable to create new Project Data using data provided.");
        }
        else {
          ((ProjectViewer) parent).updateProject(success);
        }
      }
    });
    buttonsPanel.add(cancelButton);
    cancelButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        ((ProjectViewer) parent).cancelEditProject(titleBox.getName());
      }
    });
    outer.add(buttonsPanel);

    // now populate the data into the form
    // setProjectData(pd);

    // and a little final touch
    initWidget(outer);
    ownerBox.setFocus(true);
  }

  /**
   * Takes care about adding new member in the project members list.
   *
   * @author Pavel Senin.
   *
   */
  public class NewMemberDialog extends DialogBox {
    final TextBox memId = new TextBox();

    /**
     * Initializes new member dialog.
     *
     * @param membersList The memberlist in which member will be added.
     */
    public NewMemberDialog(final ListBox membersList) {
      super(false, true);
      super.setStyleName(CSSStyles.LIST_POPUP_STYLE);
      // Set the dialog box's caption.
      setText("Enter new member e-mail");

      // Create a VerticalPanel to contain the 'about' label and the 'OK' button.
      VerticalPanel outer = new VerticalPanel();

      FlexTable ftField = new FlexTable();
      ftField.setWidget(0, 0, new Label("Member e-mail:"));
      // Create the text field
      memId.setWidth("20em");
      ftField.setWidget(0, 1, memId);
      HorizontalPanel bPanel = new HorizontalPanel();
      bPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER);
      bPanel.setWidth("100%");
      bPanel.add(new Button("OK", new ClickListener() {
        public void onClick(Widget sender) {
          membersList.addItem(memId.getText());
          hide();
        }
      }));
      bPanel.getWidget(0).setWidth("8em");
      bPanel.add(new Button("Cancel", new ClickListener() {
        public void onClick(Widget sender) {
          hide();
        }
      }));
      bPanel.getWidget(1).setWidth("8em");
      outer.add(ftField);
      outer.add(bPanel);
      setWidget(outer);
      memId.setFocus(true);
    }

    /**
     * Sets the focus on the member's field.
     */
    public void onLoad() {
      memId.setFocus(true);
    }
  }

  /**
   * Takes care about removing a member from the project members list.
   *
   * @author Pavel Senin.
   *
   */
  public static class RemoveMemberDialog extends DialogBox {
    /**
     * Initializes remove member dialog.
     *
     * @param membersList The memberlist from which member will be deleted.
     */
    public RemoveMemberDialog(final ListBox membersList) {
      // autoHide - false, modal - true
      super(false, true);
      super.setStyleName(CSSStyles.LIST_POPUP_STYLE);
      // first of all check if anything selected
      if (membersList.getItemCount() > 0 && -1 != membersList.getSelectedIndex()) {
        // Set the dialog box's caption and fix selection
        setText("Delete member?");
        final int selectionIdx = membersList.getSelectedIndex();
        String selection = membersList.getItemText(selectionIdx);
        // Create a VerticalPanel to contain the 'about' label and the 'OK' button.
        VerticalPanel outer = new VerticalPanel();

        Label memId = new Label(selection);
        outer.add(memId);
        HorizontalPanel bPanel = new HorizontalPanel();
        bPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER);
        bPanel.setWidth("100%");
        bPanel.add(new Button("OK", new ClickListener() {
          public void onClick(Widget sender) {
            membersList.removeItem(selectionIdx);
            hide();
          }
        }));
        bPanel.getWidget(0).setWidth("8em");
        bPanel.add(new Button("Cancel", new ClickListener() {
          public void onClick(Widget sender) {
            hide();
          }
        }));
        bPanel.getWidget(1).setWidth("8em");
        outer.add(bPanel);
        setWidget(outer);
      }
      else {
        Window.alert("You must select a member before deleting.");
        hide();
      }
    }

    // /**
    // * Sets the focus on the member's field.
    // */
    // public void onLoad() {
    // memId.setFocus(true);
    // }
  }

  /**
   * Takes care about adding ne URI to project.
   *
   * @author Pavel Senin.
   *
   */
  public class NewUriDialog extends DialogBox {

    final TextBox newURI = new TextBox();

    /**
     * Actual dialog.
     *
     * @param urisList The uri list we are adding new URI to.
     */
    public NewUriDialog(final ListBox urisList) {
      super(false, true);
      super.setStyleName(CSSStyles.LIST_POPUP_STYLE);
      // Set the dialog box's caption.
      setText("Enter new uri: ");
      // Create a VerticalPanel to contain the 'about' label and the 'OK' button.
      VerticalPanel outer = new VerticalPanel();

      FlexTable ftField = new FlexTable();
      ftField.setWidget(0, 0, new Label("URI:"));
      // Create the text field
      newURI.setWidth("20em");
      ftField.setWidget(0, 1, newURI);
      HorizontalPanel bPanel = new HorizontalPanel();
      bPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER);
      bPanel.setWidth("100%");
      bPanel.add(new Button("OK", new ClickListener() {
        public void onClick(Widget sender) {
          urisList.addItem(newURI.getText());
          hide();
        }
      }));
      bPanel.getWidget(0).setWidth("8em");
      bPanel.add(new Button("Cancel", new ClickListener() {
        public void onClick(Widget sender) {
          hide();
        }
      }));
      bPanel.getWidget(1).setWidth("8em");
      outer.add(ftField);
      outer.add(bPanel);
      setWidget(outer);
      newURI.setFocus(true);
    }

    // public void onLoad() {
    // newURI.setFocus(true);
    // }
  }

  /**
   * Takes care about removing a URI from the urilist.
   *
   * @author Pavel Senin.
   *
   */
  public static class RemoveUriDialog extends DialogBox {

    /**
     * Initializes remove member dialog.
     *
     * @param uriList The uriList from which uri will be deleted.
     */
    public RemoveUriDialog(final ListBox uriList) {
      // autoHide - false, modal - true
      super(false, true);
      super.setStyleName(CSSStyles.LIST_POPUP_STYLE);
      // first of all check if anything selected
      if (uriList.getItemCount() > 0 && -1 != uriList.getSelectedIndex()) {
        // Set the dialog box's caption and fix selection
        setText("Delete uri?");
        final int selectionIdx = uriList.getSelectedIndex();
        String selection = uriList.getItemText(selectionIdx);
        // Create a VerticalPanel to contain the 'about' label and the 'OK' button.
        VerticalPanel outer = new VerticalPanel();

        Label memId = new Label(selection);
        outer.add(memId);
        HorizontalPanel bPanel = new HorizontalPanel();
        bPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER);
        bPanel.setWidth("100%");
        bPanel.add(new Button("OK", new ClickListener() {
          public void onClick(Widget sender) {
            uriList.removeItem(selectionIdx);
            hide();
          }
        }));
        bPanel.getWidget(0).setWidth("8em");
        bPanel.add(new Button("Cancel", new ClickListener() {
          public void onClick(Widget sender) {
            hide();
          }
        }));
        bPanel.getWidget(1).setWidth("8em");
        outer.add(bPanel);
        setWidget(outer);
      }
      else {
        Window.alert("You must select an uri before deleting.");
        hide();
      }

      // public void onLoad() {
      // newURI.setFocus(true);
      // }

    }

  }

  /**
   * The new property addition dialog.
   *
   * @author Pavel Senin.
   *
   */
  public class NewPropDialog extends DialogBox {

    final TextBox propId = new TextBox();
    final TextBox propValue = new TextBox();

    /**
     * Creates the dialog itself.
     *
     * @param propertiesList The PROPERTIES list to use for update.
     */
    public NewPropDialog(final ListBox propertiesList) {
      super(false, true);
      super.setStyleName(CSSStyles.LIST_POPUP_STYLE);
      // Set the dialog box's caption.
      setText("Enter new property: ");

      // Create a VerticalPanel to contain the 'about' label and the 'OK' button.
      VerticalPanel outer = new VerticalPanel();
      // outer.setStyleName("listPopup");
      FlexTable ft = new FlexTable();
      ft.setWidget(0, 0, new Label("Property:"));
      ft.setWidget(1, 0, new Label("Value:"));
      // Create the text field
      // final TextBox propId = new TextBox();
      propId.setWidth("20em");
      propId.setTabIndex(1);
      ft.setWidget(0, 1, propId);
      // final TextBox propValue = new TextBox();
      propValue.setWidth("20em");
      propValue.setTabIndex(2);
      ft.setWidget(1, 1, propValue);
      Button okButton = new Button("OK", new ClickListener() {
        public void onClick(Widget sender) {
          int idx = propertiesList.getItemCount();
          propertiesList.addItem(propId.getText() + ": " + propValue.getText());
          propertiesList.setValue(idx, propValue.getText());
          hide();
        }
      });
      okButton.setWidth("10em");
      ft.setWidget(2, 0, okButton);
      Button cButton = new Button("Cancel", new ClickListener() {
        public void onClick(Widget sender) {
          hide();
        }
      });
      cButton.setWidth("10em");
      ft.setWidget(2, 1, cButton);
      outer.add(ft);
      setWidget(outer);
    }

    /**
     * Sets the focus on the property key.
     */
    public void onLoad() {
      propId.setFocus(true);
    }

  }

  /**
   * The remove property dialog.
   *
   * @author Pavel Senin.
   *
   */
  public static class RemovePropDialog extends DialogBox {

    /**
     * Creates the dialog itself.
     *
     * @param propertiesList The PROPERTIES list to use for update.
     */
    public RemovePropDialog(final ListBox propertiesList) {
      // autoHide, modal
      super(false, true);
      super.setStyleName(CSSStyles.LIST_POPUP_STYLE);
      // Set the dialog box's caption.
      if (propertiesList.getItemCount() > 0 && -1 != propertiesList.getSelectedIndex()) {
        setText("Remove property?");
        // fix selection
        final int selectionIdx = propertiesList.getSelectedIndex();
        String listEntry = propertiesList.getItemText(selectionIdx);
        int idx = listEntry.indexOf(':');
        String propKey = listEntry.substring(0, idx);
        String propValue = propertiesList.getValue(selectionIdx);
        // Create a VerticalPanel to contain the 'about' label and the 'OK' button.
        VerticalPanel outer = new VerticalPanel();

        FlexTable ft = new FlexTable();
        ft.setWidget(0, 0, new Label(propKey));
        ft.setWidget(1, 0, new Label(propValue));
        Button okButton = new Button("OK", new ClickListener() {
          public void onClick(Widget sender) {
            propertiesList.removeItem(selectionIdx);
            hide();
          }
        });
        okButton.setWidth("10em");
        ft.setWidget(1, 0, okButton);
        Button cButton = new Button("Cancel", new ClickListener() {
          public void onClick(Widget sender) {
            hide();
          }
        });
        cButton.setWidth("10em");
        ft.setWidget(1, 1, cButton);
        outer.add(ft);
        setWidget(outer);
      }
      else {
        Window.alert("You must select an uri before deleting.");
        hide();
      }
    }
    // public void onLoad() {
    // propId.setFocus(true);
    // }

  }

  /**
   * Validates the input and converts all text fields and lists data into the project data type.
   *
   * @param name The project id.
   * @param owner The project owner.
   * @param membersList The members list.
   * @param description The project description.
   * @param startDate The project start date.
   * @param endDate The project end date.
   * @param uriList The uri's list.
   * @param propertiesList The properties list.
   * @param invitations The invitation list.
   * @return The project data.
   */
  public ProjectData updateProject(String name, String owner, ListBox membersList,
      String description, String startDate, String endDate, ListBox uriList,
      ListBox propertiesList, ListBox invitations) {

    if (0 == name.length()) {
      Window.alert("Name field is empty.");
      return null;
    }

    if (0 == owner.length()) {
      Window.alert("Owner field is empty.");
      return null;
    }

    ProjectData prjData = new ProjectData();

    try {
      prjData.setName(name);
      prjData.setOwner(owner);
      prjData.setDescription(description);

      prjData.setStartTime(startDate);
      prjData.setEndTime(endDate);

      // members list
      List<String> lst = new ArrayList<String>();
      int num = membersList.getItemCount();
      for (int i = 0; i < num; i++) {
        lst.add(membersList.getItemText(i));
      }
      prjData.setMembers(lst);

      // uri list
      lst = new ArrayList<String>();
      num = uriList.getItemCount();
      for (int i = 0; i < num; i++) {
        lst.add(uriList.getItemText(i));
      }
      prjData.setUriPatterns(lst);

      // properties
      Map<String, String> mp = new HashMap<String, String>();
      num = propertiesList.getItemCount();
      for (int i = 0; i < num; i++) {
        String txt = propertiesList.getItemText(i);
        int idx = txt.indexOf(':');
        String propKey = propertiesList.getItemText(i).substring(0, idx);
        System.out.println("Property: key " + propKey + " value " + propertiesList.getValue(i));
        mp.put(propKey, propertiesList.getValue(i));
      }
      prjData.setProperties(mp);

      // invitations list
      lst = new ArrayList<String>();
      num = invitations.getItemCount();
      for (int i = 0; i < num; i++) {
        lst.add(invitations.getItemText(i));
      }
      prjData.setInvitations(lst);

      return prjData;

    }
    catch (ProjectViewerException e) {
      e.printStackTrace();
      return null;
    }

  }

  /**
   * Updates all form fields by parsing the data given.
   *
   * @param prjData The project data.
   */
  public void setProjectData(ProjectData prjData) {

    final DateTimeFormat dtf = DateTimeFormat.getFormat("MM/dd/yy");

    if (this.mode) {
      projectTitle.setSingleTitle("New Project");
    }
    else {
      projectTitle.setSingleTitle(prjData.getName());
      titleBox.setText(prjData.getName());
    }

    ownerBox.setText(prjData.getOwner());
    membersList.clear();
    List<String> mems = prjData.getMembers();
    if (!mems.isEmpty()) {
      Iterator<String> itr = mems.iterator();
      while (itr.hasNext()) {
        membersList.addItem(itr.next());
      }
    }

    descBox.setText(prjData.getDescription());
    startBox.setText(dtf.format(prjData.getStartTime()));
    endBox.setText(dtf.format(prjData.getEndTime()));

    uriList.clear();
    List<String> uris = prjData.getUriPatterns();
    if (!uris.isEmpty()) {
      Iterator<String> itr = uris.iterator();
      while (itr.hasNext()) {
        uriList.addItem(itr.next());
      }
    }

    propertiesList.clear();
    Map<String, String> props = prjData.getProperties();
    if (!props.isEmpty()) {
      Iterator<Map.Entry<String, String>> itr = props.entrySet().iterator();
      int i = 0;
      while (itr.hasNext()) {
        Entry<String, String> entry = itr.next();
        propertiesList.addItem(entry.getKey() + " : " + entry.getValue());
        propertiesList.setValue(i, entry.getValue());
        i++;
      }
    }

  }

  /**
   * Takes care about adding new member invitation.
   *
   * @author Pavel Senin.
   *
   */
  public class NewInviteeDialog extends DialogBox {
    final TextBox memId = new TextBox();

    /**
     * Initializes new member dialog.
     *
     * @param invitationsList The invitations list in which member will be added.
     */
    public NewInviteeDialog(final ListBox invitationsList) {
      super(false, true);
      super.setStyleName(CSSStyles.LIST_POPUP_STYLE);
      // Set the dialog box's caption.
      setText("Enter new invitee e-mail");

      // Create a VerticalPanel to contain the 'about' label and the 'OK' button.
      VerticalPanel outer = new VerticalPanel();

      FlexTable ftField = new FlexTable();
      ftField.setWidget(0, 0, new Label("Invitee e-mail:"));
      // Create the text field
      memId.setWidth("20em");
      ftField.setWidget(0, 1, memId);
      HorizontalPanel bPanel = new HorizontalPanel();
      bPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER);
      bPanel.setWidth("100%");
      bPanel.add(new Button("OK", new ClickListener() {
        public void onClick(Widget sender) {
          invitationsList.addItem(memId.getText());
          hide();
        }
      }));
      bPanel.getWidget(0).setWidth("8em");
      bPanel.add(new Button("Cancel", new ClickListener() {
        public void onClick(Widget sender) {
          hide();
        }
      }));
      bPanel.getWidget(1).setWidth("8em");
      outer.add(ftField);
      outer.add(bPanel);
      setWidget(outer);
      memId.setFocus(true);
    }

    /**
     * Sets the focus on the member's field.
     */
    public void onLoad() {
      memId.setFocus(true);
    }
  }

  /**
   * Takes care about removing a member from the project members list.
   *
   * @author Pavel Senin.
   *
   */
  public static class RemoveInvitationDialog extends DialogBox {
    /**
     * Initializes remove member dialog.
     *
     * @param invitationsList The invitationsList from which member will be deleted.
     */
    public RemoveInvitationDialog(final ListBox invitationsList) {
      // autoHide - false, modal - true
      super(false, true);
      super.setStyleName(CSSStyles.LIST_POPUP_STYLE);
      // first of all check if anything selected
      if (invitationsList.getItemCount() > 0 && -1 != invitationsList.getSelectedIndex()) {
        // Set the dialog box's caption and fix selection
        setText("Delete invitation?");
        final int selectionIdx = invitationsList.getSelectedIndex();
        String selection = invitationsList.getItemText(selectionIdx);
        // Create a VerticalPanel to contain the 'about' label and the 'OK' button.
        VerticalPanel outer = new VerticalPanel();

        Label memId = new Label(selection);
        outer.add(memId);
        HorizontalPanel bPanel = new HorizontalPanel();
        bPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER);
        bPanel.setWidth("100%");
        bPanel.add(new Button("OK", new ClickListener() {
          public void onClick(Widget sender) {
            invitationsList.removeItem(selectionIdx);
            hide();
          }
        }));
        bPanel.getWidget(0).setWidth("8em");
        bPanel.add(new Button("Cancel", new ClickListener() {
          public void onClick(Widget sender) {
            hide();
          }
        }));
        bPanel.getWidget(1).setWidth("8em");
        outer.add(bPanel);
        setWidget(outer);
      }
      else {
        Window.alert("You must select an invitation before deleting.");
        hide();
      }
    }

  }

  /**
   * Sets the panel mode for new project creation.
   */
  public void setModeNew() {
    GWT.log("Setting mode: new, 00 = " + ((Label) ft.getWidget(0, 0)).getText(), null);
    this.mode = true;
    if (ownerLabel.getText().equalsIgnoreCase(((Label) ft.getWidget(0, 0)).getText())) {
      GWT.log("Inserting new row", null);
      ft.insertRow(0);
      ft.setWidget(0, 0, titleLabel);
      ft.setWidget(0, 1, titleBox);
    }
    titleLabel.setVisible(true);
    titleBox.setEnabled(true);
    titleBox.setVisible(true);
  }

  /**
   * Sets the panel mode for project edition.
   */
  public void setModeEdit() {
    GWT.log("Setting mode: edit, 00 = " + ((Label) ft.getWidget(0, 0)).getText(), null);
    this.mode = false;
    if (titleLabel.getText().equalsIgnoreCase(((Label) ft.getWidget(0, 0)).getText())) {
      GWT.log("Removing row", null);
      ft.removeRow(0);
    }
    titleLabel.setVisible(false);
    titleBox.setEnabled(false);
    titleBox.setVisible(false);
  }

}
